package com.aabte.springcloudlearn.ribbonhystrixcustomerdemo.hystrix;

import com.aabte.springcloudlearn.common.beans.User;
import com.aabte.springcloudlearn.ribbonhystrixcustomerdemo.service.UserCustomerService;
import com.netflix.hystrix.HystrixCollapser;
import com.netflix.hystrix.HystrixCollapserKey;
import com.netflix.hystrix.HystrixCollapserProperties;
import com.netflix.hystrix.HystrixCommand;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;


/**
 * 请求合并器
 * 1、拦截指定时间内的单个查询请求
 * 2、将拦截到的单个查询请求合并
 * 3、查询批量查询接口
 * 4、批量查询接口返回的结果设置到单个请求中
 *
 * @author Daniel
 */
@Slf4j
public class UserCollapseCommand extends HystrixCollapser<List<User>, User, Long> {

    public static final String COMMAND_KEY = "userCollapseCommand";

    private UserCustomerService userCustomerService;
    private Long userId;

    public UserCollapseCommand(UserCustomerService userCustomerService, Long userId) {
        super(Setter.withCollapserKey(
                HystrixCollapserKey.Factory.asKey(COMMAND_KEY))
                .andCollapserPropertiesDefaults(
                        // 拦截100毫秒内的请求，然后批量查询
                        HystrixCollapserProperties.Setter().withTimerDelayInMilliseconds(100)
                ));
        this.userCustomerService = userCustomerService;
        this.userId = userId;
    }

    /**
     * 获取请求中的参数
     */
    @Override
    public Long getRequestArgument() {
        return userId;
    }

    /**
     * 创建命令，执行批量操作
     *
     * @param collapsedRequests 指定时间内的请求集合
     */
    @Override
    protected HystrixCommand<List<User>> createCommand(Collection<CollapsedRequest<User, Long>> collapsedRequests) {
        log.info("Start UserCollapseCommand.createCommand. requestSize: {}", collapsedRequests.size());
        List<Long> userIds = new ArrayList<>(collapsedRequests.size());
        userIds.addAll(collapsedRequests.stream().map(CollapsedRequest::getArgument).collect(Collectors.toList()));
        UserBatchCommand userBatchCommand = new UserBatchCommand(userCustomerService, userIds);
        log.info("End UserCollapseCommand.createCommand. userIds: {}", userIds);
        return userBatchCommand;
    }

    /**
     * 将返回的结果匹配回请求中
     *
     * @param batchResponse     批量查询的返回结果
     * @param collapsedRequests 指定时间内的请求集合
     */
    @Override
    protected void mapResponseToRequests(List<User> batchResponse, Collection<CollapsedRequest<User, Long>> collapsedRequests) {
        log.info("Start UserCollapseCommand.mapResponseToRequests. requestSize: {}", collapsedRequests.size());
        int count = 0;
        for (CollapsedRequest<User, Long> collapsedRequest : collapsedRequests) {
            // 从结果集合中按顺序取出结果
            User user = batchResponse.get(count++);
            // 将结果放回原来的Request的响应体中
            collapsedRequest.setResponse(user);
        }
        log.info("End UserCollapseCommand.mapResponseToRequests. requestSize: {}", collapsedRequests.size());
    }
}
